Inside Solaris logo
The Cobb Group This article is reprinted from the September 1996 issue of  Inside Solaris, a monthly publication of The Cobb Group.

Click for a FREE issue!


Combining find and grep to find any file anywhere

By Al Alexander

Have you ever needed to find a file that contains a particular string? It gets worse when you don't even know exactly in which directory your file resides. Recently, I had to find a file among hundreds of source files in a dozen directories. If you've ever wondered whether you can easily accomplish this under Solaris, the answer to this question is an emphatic "Yes, you can!" This is the typical situation: You've lost an important file in the maze of files within your home directory structure. You can't re-member the filename, but you do remember some of the contents of the file. Specifically, you remember that the words "treasure map" are somewhere inside that file. If only you could find it!

Search files fast with grep

As you probably know, the grep utility will do a large part of this job. You can tell grep to search a set of files for a particular string that matches a pattern. For example, if we wanted to find all the scripts in the /etc/rc2.d directory that execute the ndd command, we'd use the following commands:

$ cd /etc/rc2.d
$ grep ndd *
S69inet: set /dev/tcp ┬tcp_old_urp_interpretation 1
S69inet: set /dev/ip ip_forwarding 1
S69inet: set /dev/ip ip_forwarding 0

In this case, we're lucky. The ndd command is used only in the S69inet script. If the ndd command was used frequently in many files, the screen would quickly become unreadable.

We're interested only in the names of the files that contain the string. Luckily, grep provides the
-l option, which tells grep to print the filenames containing the string, one per line. If you don't know whether the string is capitalized or not, you can also add the -i option to let grep ignore case. Now, let's find all the scripts in the /etc/rc2.d directory that change the path. We'll do so with these commands:

$ cd /etc/rc2.d
$ grep -il path *
S47asppp
S72autoinstall
S88sendmail

Using grep, our search for the "treasure map" becomes simpler. In each directory, all we need to do is execute the command

grep -il 'treasure map' *

If only you could instruct grep to search multiple directories. As it turns out, you can. After you spec-ify the pattern, you can tell grep the filenames that you want to search. You can specify pathnames here to instruct grep to search multiple directories. For example, if you want to find the names of all the scripts that hold the string cat in the /etc/rc0.d, /etc/rc1.d, and /etc/rc2.d directories, you could type

grep -il cat /etc/rc0.d/* /etc/┬rc1.d/* /etc/rc2.d/*

As you can see, this is an unwieldy technique when you have many directories and subdirecto-ries to specify.

Adding more power with find

When you want to find a file but don't know where it is, the find command is the tool of choice. It will search a directory tree for files based on their names, ages, or other attributes. It turns out that find offers a unique and under-used option called -exec that, in combination with the grep command, gives you all the power you need to locate your file. The -exec option of the find command will tell find to execute
a command on each file it finds. Thus, we can use the find com-mand to find all the files in the directories we care about, then instruct grep to search through these files. If we want to search every file on the hard disk for the phrase "treasure map," we can do so like this:

find / -type f -exec grep -li 
┬'treasure map' {} \;

The find command begins at the root and finds all files that are files (i.e., not directories, soft links, char-acter devices, etc.). Then, for each file found, it executes the grep command to search for the phrase "treasure map." If the phrase is found, grep prints the name of the file.

The unusual syntax after the "treasure map" string is part of the required syntax for the -exec op-tion. The escaped semicolon (\;) signals the end of the -exec clause. The curly braces are a placeholder for each file that find is currently considering. The brackets hold each filename, one at a time, while grep searches through that file. You can then visualize the command as running like this:

grep -il 'treasure map' file1
grep -il 'treasure map' file2
        .
        .
        .
grep -il 'treasure map' fileN

Given my notoriously bad memory, I use this command often. For instance, recently I was looking for all of the files on my system that contained the ifconfig com-mand. I couldn't remember where I had made some network modifi-cations, but I knew my changes involved the ifconfig (interface configuration) command. All I needed to type to find the list of candidate files was

find / -type f -exec grep -il ┬ifconfig {} \;

Once I found the files containing the ifconfig command, finding the correct one was simple.

Other -exec applications

In addition to searching for text strings within files, the -exec option opens up many other possibilities. Consider for a moment that you can now run any Solaris command on every file that matches your search criteria, and you'll see that you can come up with some powerful combinations. For instance, if you're short on disk space, how about compressing every file in the home directory that hasn't been accessed in over 90 days. You can do so by typing

find /home -type f -atime +90 -exec ┬compress {} \;

Another example might be
to find all of the core dumps on the system and remove them
as follows:

find / -name core -exec rm {} \;

Or, if you're concerned about system security and setuid files owned by root, you can generate a long listing of all of these files by typing the following command:

find / -user root -perm -4000 -exec ls -ld {} \;

Of course, in addition to built-in Solaris commands, you can also run your own programs after the -exec option, including shell and Perl scripts. You'll probably want to read the man page for find to figure out other uses for the -exec option. Combining multiple search parameters and the -exec option gives you a powerful tool for your toolbox.

Conclusion

We've shown how to combine the grep and find commands with find's -exec option to search for text strings within files throughout directory trees. This is a useful way to locate files when you know part of the file contents, but not necessarily the filename. More importantly, we've also shown you other general applications of the -exec option that provide extensibility to the find command. You now have the power to say "find every file in the file system that matches my search criteria and run my command on only those files." This a powerful tool for all of your file-oriented operations.

 

[The Cobb Group Home Page]

Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.

Questions? Comments?